Bun の非互換な拡張 API
https://gyazo.com/a71f94cf1c15e71313d8a2c16c59d1ab
Bun は WinterCG meetings に参加せず、標準から外れた拡張を利便性のために結構取り入れている。またエコシステムとして合意の取れていない実装をすることもある。これら API を使ってしまうと Node.js や Deno、Cloudflare Workers などで扱えず相互運用性の問題となる。知らず知らずのうちに使ってしまわないようにまとめておく。 JS runtimes obsess about web standards but web standards orgs are incentivized to only care about browsers
@jarredsumner Just want to mention that we’ve invited you to WinterCG meetings for nearly 2 years now without any response from you - I think intentionally not participating and then saying “uh they don’t listen” is not very reasonable 😀
Web 標準 API
AsyncIterable な console で標準入力から一行ずつ読む
In Bun, the console object can be used as an AsyncIterable to sequentially read lines from process.stdin.
code: js
for await (const line of console) {
console.log(line);
}
Response のコンストラクタに AsyncIterable を渡す
code: js
const response = new Response(async function* () {
yield "hello";
yield "world";
}());
await response.text(); // "helloworld"
これは Web 標準に沿っていない。ただし Node.js (undici) でも同じように実行できてしまう。
ReadableStream.from を経由することで標準に合わせることができる。
code: js
const response = new Response(ReadableStream.from(async function* () {
yield "hello";
yield "world";
}()));
await response.text(); // "helloworld"
Headers の getAll と toJSON メソッド
Set-Cookie HTTP フィールド(ヘッダー)対応のために Headers に getAll メソッドを追加しようという議論が起きていた。
最終的に getSetCookie メソッドを追加する方向で進んでいたが、Bun は結論が出る前に getAll と toJSON を独自実装した。
The Headers class now implements the .getAll() and .toJSON() methods. These are both technically non-standard methods, but we think it will make your life easier.
code: js
const headers = new Headers();
headers.append("Set-Cookie", "a=1");
headers.append("Set-Cookie", "b=1; Secure");
console.log(headers.toJSON()); // { "set-cookie": "a=1, b=1; Secure" }
各ランタイムについての流れは Zenn に書いてある。
Fetch API の proxy オプション
In Bun, fetch supports sending requests through an HTTP or HTTPS proxy. This is useful on corporate networks or when you need to ensure a request is sent through a specific IP address.
code: js
// The URL of the proxy server
});
Worker の "open" イベント
The "open" event is emitted when a worker is created and ready to receive messages. This can be used to send an initial message to a worker once it's ready. (This event does not exist in browsers.)
code: js
const worker = new Worker(new URL("worker.ts", import.meta.url).href);
worker.addEventListener("open", () => {
console.log("worker is ready");
});
Worker が起動されるまでに送られたメッセージはキューに入れられるため、特に待つ必要はない。
Text Modules
WHATWG で Import Attributes を使った type: "text" の提案がなされている。エンコーディングをどう指定するかなどの議論が起きている。 Bun は結論を待たず、すでに独自実装している。
code: js
import html from "./index.html" with { type: "text" };
console.log(html);
JSX
ショートハンド記法
code: jsx
function Div(props: {className: string;}) {
const {className} = props;
// without punning
return <div className={className} />;
// with punning
return <div {className} />;
}
JSX の仕様は Meta (Facebook) により管理されている。
特に仕様に対して提案するといったアプローチをとることなく拡張し、他ランタイムへ足並みを揃えるよう呼びかけず、急に TypeScript のパーサーへの対応を要求したため議論を呼んだ。リジェクトされた。
In bun's current implementation, we don't support multiple identifiers in one {}, just <div {foo} />. The rationale was to keep the parser changes as simple as possible and minimize edgecases. From a DX perspective, it would be better to support multiple but I think it's still net improvement to ship without supporting it
Node.js
package.json で JSONC 形式の対応
突然 package.json で JSONC 形式の対応を表明したため賛否両論が巻き起こった。
In the next version of Bun
Bun won't error when package.json has comments or trailing commas
https://gyazo.com/452b2309ebecb504a0163eb4d645524d
PR にネガティブな意見が集まったが、最終的に Jarred 氏が Twitter 上のアンケート結果を根拠として Bun に取り込んだ。
JSONC 形式の場合当然 npm にパブリッシュ出来ない。互換性がないのだから拡張子を jsonc にしてサポートした方がいいのにと個人的には思う。
その他
TOML Modules
code: js
import data from "./data.toml";
// there's no toml extension, but type makes it read as toml.
import cfg from "./Configfile" with { type: "toml" };